//
//  CConfiguration.m
//  collection
//
//  Created by 张靖 on collection-1.
//  Copyright 2011年 collection. Inc.. All rights reserved.
//

#import "CConfiguration.h"
#import "CRandom.h"

#include <sys/socket.h> // Per msqr
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>

#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>

#define KAppSettingConfigName           @"sysconfig.plist"
#define USER_LOGIN_INFO_FILE      @"UserInfo"
#define ANONYMOUS_USER_PATH       @"Anonymous"


@interface CConfiguration()

@property (nonatomic, retain) NSString* uniqueID;

- (NSString*) getUniqueIDPath;

@end

@implementation CConfiguration

@synthesize uniqueID = _uniqueID;
@synthesize deviceToken = _deviceToken;

static CConfiguration* _sharedConfiguration = nil;
+ (CConfiguration*) sharedConfiguration
{
	if (_sharedConfiguration == nil)
	{
		_sharedConfiguration = [[CConfiguration alloc] init];
	}	
	return _sharedConfiguration;
}

+ (id) alloc
{
	NSAssert(_sharedConfiguration == nil, @"Attempted to allocate a second instance of a singleton.");
	return [super alloc];
}

+ (void) purgeSharedConfiguration
{
	[_sharedConfiguration release];
}

- (id) init
{
	if ((self = [super init])) 
	{
        // default values
        
        self.uniqueID = nil;
        self.deviceToken = nil;

        [self readDeviceTokenFromLocal];
    }
    return self;
}

- (void)dealloc 
{
    self.uniqueID = nil;
    self.deviceToken = nil;
    
    [super dealloc];
}

- (NSString*) getAppDocPath
{
	static NSString* sAPPDOCPATH = nil;
	if (sAPPDOCPATH == nil)
	{
		NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
		if ([paths count] > 0)
		{
			sAPPDOCPATH = [[NSString alloc] initWithString:[paths objectAtIndex:0]];
		}
	}
	return sAPPDOCPATH;
}

- (NSString*) getAppCachePath
{
	static NSString* sAPPCACHEPATH = nil;
	if (sAPPCACHEPATH == nil)
	{
		NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
		if ([paths count] > 0)
		{
			sAPPCACHEPATH = [[NSString alloc] initWithString:[paths objectAtIndex:0]];
		}
	}
	return sAPPCACHEPATH;
}

- (NSString*) getFullPath:(NSString*) filename pathtype:(TPathType)type
{
	if(([filename length] > 0) && ([filename characterAtIndex:0] == '/'))
	{
		return filename;
	}
	
	NSString* tFullPath = nil;
	if (type == kPathForDocument)
	{
		NSString* tRootPath = [self getAppDocPath];
		tFullPath = [NSString stringWithFormat:@"%@/%@", tRootPath, filename];
	}
	else if (type == kPathForCache)
	{
		NSString* tRootPath = [self getAppCachePath];
		tFullPath = [NSString stringWithFormat:@"%@/%@", tRootPath, filename];
	}
	else if (type == kPathForBundle)
	{
		tFullPath = [[NSBundle mainBundle] pathForResource:filename ofType:nil];
	}
    else if ( type == kPathForFileCache )
    {
        NSString* tRootPath = [self getAppCachePath];
		tFullPath = [NSString stringWithFormat:@"%@/FileCache/%@", tRootPath, filename];
    }
    else if ( type == kPathForDBCache )
    {
        NSString* tRootPath = [self getAppCachePath];
		tFullPath = [NSString stringWithFormat:@"%@/DBCache/%@", tRootPath, filename];
    }
	else 
	{
		NSAssert(NO, @"参数错误");
	}
	return tFullPath;
}


- (NSString*) getPathByType:(TPathType)type
{	
	NSString* tFullPath = nil;
	if (type == kPathForDocument)
	{
		tFullPath = [self getAppDocPath];
	}
	else if (type == kPathForCache)
	{
		tFullPath = [self getAppCachePath];
	}
	else if (type == kPathForBundle)
	{
		tFullPath = [[NSBundle mainBundle] bundlePath];
	}
    else if ( type == kPathForFileCache )
    {
        NSString* tRootPath = [self getAppCachePath];
		tFullPath = [NSString stringWithFormat:@"%@/FileCache/", tRootPath];
    }
    else if ( type == kPathForDBCache )
    {
        NSString* tRootPath = [self getAppCachePath];
		tFullPath = [NSString stringWithFormat:@"%@/DBCache/", tRootPath];
    }
	else 
	{
		NSAssert(NO, @"参数错误");
	}
	return tFullPath;
}


- (UIImage*) getBundleImage:(NSString*)imagePath
{
	UIImage* bundleImage = nil;
	NSString* path = [self getFullPath:imagePath pathtype:kPathForBundle];
	if (path != nil)
	{
		bundleImage = [[[UIImage alloc] initWithContentsOfFile:path] autorelease];
	}
	NSAssert(bundleImage != nil, @"图片不存在");
	return bundleImage;
}

- (NSString*) getDateString:(NSString*)format date:(NSDate*)date
{
	NSDateFormatter* formatter = [[[NSDateFormatter alloc] init] autorelease];
    [formatter setDateFormat:format];
    NSString* dataStr = [formatter stringFromDate:date];
    return dataStr;
}

-(NSString*) getDateNowString:(NSString*)format
{
    NSDate* date = [NSDate date];
    return [self getDateString:format date:date];
}

- (NSData*) readDataFromLocal:(NSString*)fileName
{
	NSAssert(fileName != nil, @"参数错误");
	NSData* data = nil;
	NSString* path = [self getFullPath:fileName pathtype:kPathForCache];
	CFileHandle* tFileHandle = [CFileHandle fileHandleForReadAtPath:path];
	if (tFileHandle != nil)
	{
		data = [tFileHandle readData];
	}
	return data;
}

- (void) saveDataToLocal:(NSString*)fileName data:(NSData*)data
{
	NSAssert(fileName != nil, @"参数错误");
	if (data == nil)
	{
		return;
	}
	NSString* path = [self getFullPath:fileName pathtype:kPathForCache];
	if (path == nil) return;
	
	CFileHandle* tFileHandle = [CFileHandle fileHandleForWriteAtPath:path];
	if (tFileHandle == nil) return;
	
	[tFileHandle writeData:data];
}

- (NSString*) getCellCarrierName
{
    CTTelephonyNetworkInfo * cellphoneinfo = [[CTTelephonyNetworkInfo alloc] init];
    CTCarrier * carrier = cellphoneinfo.subscriberCellularProvider;
    
    // 注释 by 张靖
    // carrier name -> 运营商名称。只要用户连接一次运营商网络便会被记录，当手机处于Airplane mode，或无sim卡，无网络时也能获取
    // mobileCountryCode /  mobileNetworkCode 当手机处于Airplane mode、无sim卡或无网络时候为nil 
    
    // 使用卡贴的手机无法准确识别运营商名称
    
    NSString* carrierInfo = @"";
    if(carrier && carrier.carrierName)
    {
        carrierInfo = [NSString stringWithFormat:@"%@", carrier.carrierName];
    }
    
//    if(carrier && carrier.mobileNetworkCode)
//    {
//        [carrierInfo appendFormat:@"%@=%@\r\n", @"mobileNetworkCode", carrier.mobileNetworkCode];
//    }
    
    [cellphoneinfo release];
    
    XLOG(@"Carrier info = [%@]", carrierInfo);
    
    return carrierInfo;
}

// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Accidentally munged during previous update. Fixed thanks to mlamb.
- (NSString *) macAddress
{
    int                    mib[6];
    size_t                len;
    char                *buf;
    unsigned char        *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl    *sdl;
	
    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;
	
    if ((mib[5] = if_nametoindex("en0")) == 0) {
        XLOG("Error: if_nametoindex error/n");
        return nil;
    }
	
    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        XLOG("Error: sysctl, take 1/n");
        return nil;
    }
	
    if ((buf = (char*)malloc(len)) == NULL) {
        XLOG("Could not allocate memory. error!/n");
        return nil;
    }
	
    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        XLOG("Error: sysctl, take 2");
        return nil;
    }
	
    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    // NSString *outstring = [NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    NSString *outstring = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    free(buf);
    return [outstring uppercaseString];
}

- (NSString*) getUniqueID
{
	if (self.uniqueID == nil) 
	{
		NSString* path = [self getUniqueIDPath];
		NSFileManager* tFileManager = [NSFileManager defaultManager];
		if ([tFileManager fileExistsAtPath:path])
		{
			CFileHandle* tFileHandle = [CFileHandle fileHandleForReadAtPath:path];
			if (tFileHandle == nil) return nil;
			
			self.uniqueID = (NSString *)[NSKeyedUnarchiver unarchiveObjectWithData:[tFileHandle readData]];
		}
		
		if (self.uniqueID == nil)
		{
			NSString* macaddr = [self macAddress];
			if (macaddr != nil)
			{
				self.uniqueID = [CMD5Util md5String:macaddr];
			}
            
            if (self.uniqueID != nil) 
            {
                // 写入文件
                CFileHandle* tFileHandle = [CFileHandle fileHandleForWriteAtPath:path];
                if (tFileHandle == nil) return nil;
                
                [tFileHandle writeData:[NSKeyedArchiver archivedDataWithRootObject:self.uniqueID]];
            }
		}
		
		if (self.uniqueID == nil || [self.uniqueID length] < 3)
		{
			CFileHandle* tFileHandle = [CFileHandle fileHandleForWriteAtPath:path];
			if (tFileHandle == nil) return nil;
			
			NSString *deviceid = [NSString stringWithFormat:@"%u%u",[CRandom getRandomNum:1000 max:100000000], (int)time(0)];
            self.uniqueID = [CMD5Util md5String:deviceid];
			[tFileHandle writeData:[NSKeyedArchiver archivedDataWithRootObject:self.uniqueID]];
		}
        
        XLOG(@"device unique id = %@", self.uniqueID);
	}
	
	return self.uniqueID;
}

- (NSString*) getUniqueIDPath
{
	return [self getFullPath:@"uniqueid.value" pathtype:kPathForCache];
}

- (NSString*) getDeviceTokenPath
{
	return [self getFullPath:@"devicetoken.value" pathtype:kPathForCache];
}

- (NSString*) getDeviceToken
{
    return self.deviceToken;
}

- (void) setAndSaveDeviceToken:(NSString*)deviceToken
{
    NSString* path = [self getDeviceTokenPath];
	if (path == nil) return;
	
	CFileHandle* tFileHandle = [CFileHandle fileHandleForWriteAtPath:path];
	if (tFileHandle == nil) return;
	
	const char* tStr = [deviceToken UTF8String];
    NSData* tNewData = [NSData dataWithBytes:tStr length:strlen(tStr)+1];
	[tFileHandle writeData:tNewData];
}

- (void) readDeviceTokenFromLocal
{
	NSString* path = [self getDeviceTokenPath];
	if (path != nil)
	{
		CFileHandle* tFileHandle = [CFileHandle fileHandleForReadAtPath:path];
		if (tFileHandle != nil)
		{
			NSData* tData = [tFileHandle readData];
			if (tData != nil)
			{
				const char* tStr = (const char*)[tData bytes];
				NSString* tokenStr = [[NSString alloc] initWithCString:tStr encoding:NSUTF8StringEncoding];
                self.deviceToken = tokenStr;
                [tokenStr release];
			}
		}
	}
}

- (NSString*)filePath:(NSString*)fileName underUser:(NSString*)userID pathType:(TPathType)type
{
    /*
    //
    // 匿名账号
    if ( (nil == userID) || ([userID isEqualToString:@""])) 
    {
        //
        if (fileName != nil) 
        {
            return [[CConfiguration sharedConfiguration] getFullPath:[NSString stringWithFormat:@"%@/%@", ANONYMOUS_USER_PATH, fileName] pathtype:type];
        }
        else
        {
            return [[CConfiguration sharedConfiguration] getFullPath:ANONYMOUS_USER_PATH pathtype:type];
        }
    }
    else
    {
        if (fileName != nil) 
        {
            return [[CConfiguration sharedConfiguration] getFullPath:[NSString stringWithFormat:@"%@/%@", userID, fileName] pathtype:type];
        }
        else
        {
            return [[CConfiguration sharedConfiguration] getFullPath:userID pathtype:type];
        }
    }
     */
    NSString* userRootFolder = @"";
    
    if ( (nil == userID) || ([userID isEqualToString:@""])) 
    {
        userRootFolder = [[CConfiguration sharedConfiguration] getFullPath:ANONYMOUS_USER_PATH pathtype:type];
    }
    else
    {
        userRootFolder = [[CConfiguration sharedConfiguration] getFullPath:userID pathtype:type];
    }
    
    [self checkAndCreateDirectory:userRootFolder];
    
    if (fileName != nil) 
    {
        return [NSString stringWithFormat:@"%@/%@", userRootFolder, fileName];
    }
    else
    {
        return userRootFolder;
    }
}

- (NSString*)filePath:(NSString*)fileName underUser:(NSString*)userID;
{
    return [self filePath:fileName underUser:userID pathType:kPathForDocument];
}

- (void)checkAndCreateDirectory:(NSString*)directoryPath
{
    BOOL isDir;
    NSFileManager *fileManager = [NSFileManager defaultManager];

    if ([fileManager fileExistsAtPath:directoryPath isDirectory:&isDir] == NO)
    {
        // 文件或文件夹不存在
        [fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:NO attributes:nil error:nil];
    }
    else 
    {
        // 目标地址是文件而不是文件夹
        if (isDir == NO) 
        {
            [fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:NO attributes:nil error:nil];
        }
    }
}

- (NSString*)filePath:(NSString*)fileName underUser:(NSString*)userID underTrip:(long)tripID pathType:(TPathType)type
{
    NSString* userRootFolder = @"";
    NSString* tripRootFolder = @"";
    
    //
    // 匿名账号
    if ( (nil == userID) || ([userID isEqualToString:@""])) 
    {
        userRootFolder = [[CConfiguration sharedConfiguration] getFullPath:ANONYMOUS_USER_PATH pathtype:type];
    }
    else
    {
        userRootFolder = [[CConfiguration sharedConfiguration] getFullPath:userID pathtype:type];
    }
    
    tripRootFolder = [NSString stringWithFormat:@"%@/%ld", userRootFolder, tripID];
    
    [self checkAndCreateDirectory:userRootFolder];
    [self checkAndCreateDirectory:tripRootFolder];
    
    NSString* filePath = [NSString stringWithFormat:@"%@/%@", tripRootFolder, fileName];
    
    return filePath;
}

- (NSString*)filePath:(NSString*)fileName underUser:(NSString*)userID underTrip:(long)tripID
{
    return [self filePath:fileName underUser:userID underTrip:tripID pathType:kPathForDocument];
}

@end
